﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using PlaylistEditorForCentrafuse.Logging;
using PlaylistEditorForCentrafuse.Playlist;
using Utils;

namespace PlaylistEditorForCentrafuse.GUI
{
    public partial class frmEditor : Form
    {
        #region Enums
        public enum ColumnsAudiofile
        {
            Filename,
            NoOfPlaylists,
            Tags,
            Cover,
            Lyrics
        }

        public enum ColumnsPlaylistfile
        {
            Filename,
            NoOfSongs,
            MissingCount,
            DuplicateCount,
            Type
        }

        public enum ColumnsPlaylistContents
        {
            Filename,
            Title,
            Artist,
            Album,
            Genre,
            Track,
            Year
        }
        #endregion

        #region Private Members
        
        // Audio- und Playlistfile Arrays
        private List<PlaylistAudioFile> _audioFiles = new List<PlaylistAudioFile>();
        private List<PlaylistFile> _playlistFiles = new List<PlaylistFile>();

        // Forms
        private frmAudioFileDetails _frmAudioDetails = new frmAudioFileDetails();
        private frmPlaylistDetails _frmPlaylistDetails = new frmPlaylistDetails();
        private frmEntryDetails _frmEntryDetails = new frmEntryDetails();
        
        // Filter
        private List<ListViewItem> _listViewItemBuffer = null;
        private string _currentFilter = string.Empty;

		// Logging
		private LogFile _logFile = new LogFile(Application.ProductName + ".log");

        #endregion

        #region Konstruktor

        public frmEditor()
        {
            InitializeComponent();

            // Listview Sorter
            lstAudioFiles.ListViewItemSorter = 
                new ListViewColumnSorter(new int[] {(int)ColumnsAudiofile.NoOfPlaylists});
            lstPlaylists.ListViewItemSorter = 
                new ListViewColumnSorter(new int[] {(int)ColumnsPlaylistfile.NoOfSongs, 
                                                    (int)ColumnsPlaylistfile.MissingCount,
                                                    (int)ColumnsPlaylistfile.DuplicateCount});

			// Einstellungen
			menuProtocol.Checked = Properties.Settings.Default.WriteProtocol;
            menuPlaylistCF2.Checked = !Properties.Settings.Default.UseCF3StyleMPL;
            menuPlaylistCF3.Checked = Properties.Settings.Default.UseCF3StyleMPL;
			menuPlaylistAutoSort.Checked = Properties.Settings.Default.AutoSortPlaylistEntries;
			
			_logFile.EnableLogging = menuProtocol.Checked;
        }
        
        #endregion

        #region Event Handler

        private void beendenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void btnSelectMusicPath_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                txtMusicPath.Text = folderBrowserDialog.SelectedPath;
                GetAudioFiles();
            }
        }

        private void lstPlaylists_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Nur aktualisieren, wenn nicht bereits angezeigt
            if (lstPlaylists.SelectedItems.Count == 1)
            {
                ShowPlaylistContents(lstPlaylists.SelectedItems[0].Tag as PlaylistFile);
            }
            else
            {
                lstPlaylistEntries.Items.Clear();
                grpPlaylistEntries.Text = "Playlisteinträge";
            }
        }

        private void frmEditor_FormClosing(object sender, FormClosingEventArgs e)
        {
            // Änderungen speichern
            foreach (PlaylistFile playlist in _playlistFiles)
            {
                if (CheckForSaveNeed(playlist) == false)
                {
                    e.Cancel = true;
                    break;
                }
            }// for (int i = 0; i < playlistProps.Count; i++)
        }

        private void lstPlaylists_DragEnter(object sender, DragEventArgs e)
        {
            // Nur Dateien erlauben
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void lstPlaylists_DragDrop(object sender, DragEventArgs e)
        {
            AddMultiplePlaylists((string[])e.Data.GetData(DataFormats.FileDrop));
        }

        private void lstAudioFiles_ItemDrag(object sender, ItemDragEventArgs e)
        {
            // Drag Starten
            if (lstAudioFiles.SelectedItems.Count > 0)
            {
                List<PlaylistAudioFile> files = new List<PlaylistAudioFile>();

                foreach (ListViewItem item in lstAudioFiles.SelectedItems)
                {
                    files.Add(item.Tag as PlaylistAudioFile);
                }

                lstAudioFiles.DoDragDrop(files, DragDropEffects.Copy);
            }// if (lstAudioFiles.SelectedItems.Count > 0)
        }

        private void lstAudioFiles_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            // Doppelklick -> Detailfenster
            if (lstAudioFiles.SelectedItems.Count == 1)
            {
                AudiofileShowDetails(lstAudioFiles.SelectedItems[0].Tag as PlaylistAudioFile);
            }
        }

        private void menuQueryTagInfos_Click(object sender, EventArgs e)
        {
            pbarStatusStrip.Maximum = _audioFiles.Count;
            pbarStatusStrip.Value = 0;

            // Imagelists abkoppeln
            lstAudioFiles.LargeImageList = null;
            lstAudioFiles.SmallImageList = null;

            bgwQueryTagInfos.RunWorkerAsync();
        }

        private void menuAudiofiles_DropDownOpening(object sender, EventArgs e)
        {
            menuQueryTagInfos.Enabled = _audioFiles.Count > 0 && bgwQueryTagInfos.IsBusy == false;
        }

        private void bgwQueryTagInfos_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 0; i < _audioFiles.Count && worker.CancellationPending == false; i++)
            {
                // Tags abrufen
                if (_audioFiles[i].LoadTags(false))
                {
                    // Albumcover zu Imagelist hinzufügen
                    if (_audioFiles[i].ID3v2.Picture != null)
                    {
                        imageListLarge.Images.Add(_audioFiles[i].FileName,
                                                  _audioFiles[i].ID3v2.Picture);
                        imageListSmall.Images.Add(_audioFiles[i].FileName,
                                                  _audioFiles[i].ID3v2.Picture);
                    }
                    worker.ReportProgress(i);
                }// if (_audioFiles[i].LoadTags(false))
            }// for (int i = 0; i < audioFileProps.Count && worker.CancellationPending == false; i++)
        }

        private void bgwQueryTagInfos_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // Progressbar anzeigen
            if (pbarStatusStrip.Visible == false)
            {
                pbarStatusStrip.Visible = true;
            }
            
            ++pbarStatusStrip.Value;
            lblStatusStrip.Text = "Taginformationen werden abgerufen (" +
                (e.ProgressPercentage + 1) + " von " + _audioFiles.Count + ")...";
        }

        private void bgwQueryTagInfos_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {            
            pbarStatusStrip.Visible = false;
            lblStatusStrip.Text = _audioFiles.Count.ToString() + " Taginformationen abgerufen.";

            // Imagelist wieder anfügen
            lstAudioFiles.LargeImageList = imageListLarge;
            lstAudioFiles.SmallImageList = imageListSmall;

            // Anzeige aktualisieren
            foreach (PlaylistAudioFile audiofile in _audioFiles)
            {
                audiofile.UpdateListView();
            }
        }

        private void frmEditor_Load(object sender, EventArgs e)
        {
			_logFile.WriteLine("frmEditor_Load: Loading started");
        
            lblStatusStrip.Text = "";

			// Centrafuse Path laden
			txtCentrafusePath.Text = Properties.Settings.Default.CentrafusePath;
            
            // Sortierung initialisieren
            SetSortColumnAudiofiles(ColumnsAudiofile.NoOfPlaylists);
            ListViewExtensions.ChangeSorting(lstPlaylists, (int) ColumnsPlaylistfile.Filename);

            // ListView Ansicht setzen
            SetViewAudiofiles(View.Details);
            
            // Audiodateien abrufen
            GetAudioFiles();

            // Zuletzt geöffnete Playlisten laden
            if (Properties.Settings.Default.Playlistfiles != null)
            {
                foreach (string filename in Properties.Settings.Default.Playlistfiles)
                {
                    AddPlaylist(filename);
                }

                // Sortieren
                lstPlaylists.Sort();
                lstAudioFiles.Sort();
            }
			_logFile.WriteLine("frmEditor_Load: Playlists loaded(" + _playlistFiles.Count + ")");
			_logFile.WriteLine("frmEditor_Load: Loading finished");
        }

        private void menuFile_DropDownOpening(object sender, EventArgs e)
        {
            menuFileSave.Enabled = lstPlaylists.SelectedItems.Count > 0;
            menuFileSaveAs.Enabled = lstPlaylists.SelectedItems.Count > 0;
        }

        private void menuFileSave_Click(object sender, EventArgs e)
        {
            // Datei speichern
            foreach (ListViewItem item in lstPlaylists.SelectedItems)
            {
				(item.Tag as PlaylistFile).WritePlaylist();
            }
        }

        private void menuFileSaveAs_Click(object sender, EventArgs e)
        {
            // Datei speichern unter
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Title = "Playliste speichern unter";
            dlg.Filter = "M3U Playlisten (*.m3u)|*.m3u|MPL Playlisten (*.mpl)|*.mpl";
            
            PlaylistFile playlist;
            foreach (ListViewItem item in lstPlaylists.SelectedItems)
            {
                playlist = item.Tag as PlaylistFile;

                // Dialogeinstellungen
                dlg.FileName = Path.GetFileName(playlist.Filename);
                dlg.InitialDirectory = Path.GetDirectoryName(playlist.Filename);
				dlg.FilterIndex = playlist.Type == PlaylistTypeEnum.M3U ? 1 : 2;

                // Speichern
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    if (dlg.FilterIndex == 1)
                    {
                        playlist.Type = PlaylistTypeEnum.M3U;
                    }
                    else
                    {
                        playlist.Type = PlaylistTypeEnum.MPL;
                    }

                    playlist.Filename = dlg.FileName;

                    playlist.WritePlaylist();
                    
                }
            }// for (int i = 0; i < lstPlaylists.SelectedItems.Count; i++)
        }

        private void lstPlaylistEntries_DragEnter(object sender, DragEventArgs e)
        {
            // Nur wenn eine Playlist aktiv ist
            if (lstPlaylists.SelectedItems.Count == 1)
            {
                // Nur Audiodateien aus Liste erlauben
                if (e.Data.GetDataPresent(_audioFiles.GetType()))
                {
                    e.Effect = DragDropEffects.Copy;
                }
                else
                {
                    e.Effect = DragDropEffects.None;
                }
            }// if (lstPlaylists.SelectedItems.Count > 0)
        }

        private void lstPlaylistEntries_DragDrop(object sender, DragEventArgs e)
        {
            bool added = false;

            foreach (PlaylistAudioFile file in (List<PlaylistAudioFile>)e.Data.GetData(_audioFiles.GetType()))
            {
                if (AddFileToPlaylist(file, lstPlaylists.SelectedItems[0].Tag as PlaylistFile))
                {
                    // Audiofiles aktualisieren
                    added = true;
                }
            }

            if (added)
            {
				if (Properties.Settings.Default.AutoSortPlaylistEntries)
				{
					SortSelectedPlaylists();
				}
				else
				{
					ShowPlaylistContents(lstPlaylists.SelectedItems[0].Tag as PlaylistFile);
				}
            }// if (added)
        }

        private void frmEditor_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Backgroundworker stoppen
            bgwQueryTagInfos.CancelAsync();
            bgwQueryTagInfos.RunWorkerCompleted -= bgwQueryTagInfos_RunWorkerCompleted;
            bgwQueryTagInfos.ProgressChanged -= bgwQueryTagInfos_ProgressChanged;

            // Einstellungen speichern
            // Geöffnete Playlisten
            Properties.Settings.Default.Playlistfiles = new System.Collections.Specialized.StringCollection();
            foreach (PlaylistFile playlist in _playlistFiles)
            {
                Properties.Settings.Default.Playlistfiles.Add(playlist.Filename);
            }
        }

        private void lstPlaylists_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            PlaylistShowDetails();
        }

        private void lstPlaylistEntries_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            PlaylistEntryEdit();
        }

        private void menuNewPlaylist_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "M3U Playlisten (*.m3u)|*.m3u|MPL Playlisten (*.mpl)|*.mpl";
            dlg.RestoreDirectory = true;
            dlg.Title = "Neue Playliste speichern unter";

            // Neue Playlist hinzufügen
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                PlaylistTypeEnum type;
                if (dlg.FilterIndex == 0)
                {
                    type = PlaylistTypeEnum.M3U;
                }
                else
                {
                    type = PlaylistTypeEnum.MPL;
                }
                _playlistFiles.Add(new PlaylistFile(dlg.FileName, type, menuPlaylistCF3.Checked));

                ShowPlaylistFile(_playlistFiles.Last());
            }// if (dlg.ShowDialog() == DialogResult.OK)
        }

        private void contextMenuEntries_Opening(object sender, CancelEventArgs e)
        {
            // Enable - Disable
            cMenuEntriesEdit.Enabled = lstPlaylistEntries.SelectedItems.Count == 1;
            cMenuEntriesDelete.Enabled = lstPlaylistEntries.SelectedItems.Count > 0;
            cMenuEntriesSort.Enabled = lstPlaylistEntries.Items.Count > 0;
            cMenuEntriesRefreshID3.Enabled = lstPlaylistEntries.SelectedItems.Count > 0;

            cMenuEntriesDetails.Enabled = false;
            if (lstPlaylistEntries.SelectedItems.Count == 1)
            {
                if (lstPlaylistEntries.SelectedItems[0].Group != lstPlaylistEntries.Groups["grpPlEntriesMissing"])
                {
                    cMenuEntriesDetails.Enabled = true;
                }
            }
        }

        private void cMenuEntriesEdit_Click(object sender, EventArgs e)
        {
            PlaylistEntryEdit();
        }

        private void contextMenuAudiofiles_Opening(object sender, CancelEventArgs e)
        {
            cMenuAudioDetails.Enabled = lstAudioFiles.SelectedItems.Count == 1;
        }

        private void cMenuEntriesDetails_Click(object sender, EventArgs e)
        {
            if (lstPlaylistEntries.SelectedItems.Count == 1)
            {
                AudiofileShowDetails((lstPlaylistEntries.SelectedItems[0].Tag as PlaylistEntry).Audiofile);
            }// if (lstPlaylistEntries.SelectedItems.Count == 1)
        }

        private void cMenuEntriesDelete_Click(object sender, EventArgs e)
        {
            PlaylistEntryDelete();
        }

        private void cMenuEntriesSort_Click(object sender, EventArgs e)
        {
			SortSelectedPlaylists();
        }

        private void contextMenuPlaylists_Opening(object sender, CancelEventArgs e)
        {
            cMenuPlaylistsDelete.Enabled = lstPlaylists.SelectedItems.Count > 0;
            cMenuPlaylistsDeleteAll.Enabled = lstPlaylists.Items.Count > 0;
            cMenuPlaylistsDetails.Enabled = lstPlaylists.SelectedItems.Count == 1;
        }

        private void cMenuPlaylistsDetails_Click(object sender, EventArgs e)
        {
            PlaylistShowDetails();
        }

        private void cMenuPlaylistsDelete_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in lstPlaylists.SelectedItems)
            {
                PlaylistDelete(item.Tag as PlaylistFile);
            }
        }

        private void cMenuPlaylistsDeleteAll_Click(object sender, EventArgs e)
        {
            for (int i = _playlistFiles.Count - 1; i > -1; i-- )
            {
                PlaylistDelete(_playlistFiles[i]);
            }
        }

        private void menuOpenPlaylist_Click(object sender, EventArgs e)
        {
            if (openPlaylistsDialog.ShowDialog() == DialogResult.OK)
            {
                AddMultiplePlaylists(openPlaylistsDialog.FileNames);
            }// if (openPlaylistsDialog.ShowDialog() == DialogResult.OK)
        }

        private void cMenuAudioDetails_Click(object sender, EventArgs e)
        {
            if (lstAudioFiles.SelectedItems.Count == 1)
            {
                AudiofileShowDetails(lstAudioFiles.SelectedItems[0].Tag as PlaylistAudioFile);
            }
        }

        private void lstAudioFiles_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            SetSortColumnAudiofiles((ColumnsAudiofile)e.Column);
        }

        private void lstPlaylists_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            ListViewExtensions.ChangeSorting(lstPlaylists, e.Column);
        }

        private void cMenuAudioViewDetails_Click(object sender, EventArgs e)
        {           
            SetViewAudiofiles(View.Details);
        }

        private void cMenuAudioViewList_Click(object sender, EventArgs e)
        {
            SetViewAudiofiles(View.List);
        }

        private void cMenuAudioViewSymbols_Click(object sender, EventArgs e)
        {
            SetViewAudiofiles(View.SmallIcon);
        }

        private void cMenuAudioViewLargeIcon_Click(object sender, EventArgs e)
        {
            SetViewAudiofiles(View.LargeIcon);
        }

        private void cMenuAudioViewTile_Click(object sender, EventArgs e)
        {
            SetViewAudiofiles(View.Tile);
        }

        private void cMenuAudioOrderByFilename_Click(object sender, EventArgs e)
        {
            SetSortColumnAudiofiles(ColumnsAudiofile.Filename);
        }

        private void cMenuAudioOrderByPlaylists_Click(object sender, EventArgs e)
        {
            SetSortColumnAudiofiles(ColumnsAudiofile.NoOfPlaylists);
        }

        private void cMenuAudioOrderByTags_Click(object sender, EventArgs e)
        {
            SetSortColumnAudiofiles(ColumnsAudiofile.Tags);
        }

        private void cMenuAudioOrderByCover_Click(object sender, EventArgs e)
        {
            SetSortColumnAudiofiles(ColumnsAudiofile.Cover);
        }

        private void cMenuAudioOrderByLyrics_Click(object sender, EventArgs e)
        {
            SetSortColumnAudiofiles(ColumnsAudiofile.Lyrics);
        }

        private void txtFilterAudiofiles_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return)
            {
                FilterAudiofiles();
            }
        }

        private void txtFilterAudiofiles_Leave(object sender, EventArgs e)
        {
            FilterAudiofiles();
        }

		private void menuProtocol_Click(object sender, EventArgs e)
		{
			Properties.Settings.Default.WriteProtocol = menuProtocol.Checked = !menuProtocol.Checked;
			_logFile.EnableLogging = menuProtocol.Checked;
		}

        private void menuPlaylistCF2_Click(object sender, EventArgs e)
        {
            SwitchMPLPlaylistVersion();
        }

        private void menuPlaylistCF3_Click(object sender, EventArgs e)
        {
            SwitchMPLPlaylistVersion();
        }

        private void cMenuEntriesRefreshID3_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            foreach (ListViewItem item in lstPlaylistEntries.SelectedItems)
            {
                (item.Tag as PlaylistEntry).RefreshDetails();
            }

            Cursor = Cursors.Default;
        }

		private void btnApplyReplaceString_Click(object sender, EventArgs e)
		{
			btnApplyReplaceString.Enabled = false;
			Properties.Settings.Default.CentrafusePath = txtCentrafusePath.Text;

			// Replace Centrafuse Path with Local Path, same as loading
			ReplaceAllPlaylistPaths();

			// Update the files
			foreach(PlaylistFile playlist in _playlistFiles)
			{
				playlist.CalcProperties(_audioFiles);
			}
		}

		private void txtCentrafusePath_TextChanged(object sender, EventArgs e)
		{
			if (!btnApplyReplaceString.Enabled
				&& txtCentrafusePath.Text != Properties.Settings.Default.CentrafusePath)
			{
				btnApplyReplaceString.Enabled = true;
			}
		}

		private void menuPlaylistAutoSort_Click(object sender, EventArgs e)
		{
			Properties.Settings.Default.AutoSortPlaylistEntries = menuPlaylistAutoSort.Checked;
		}
        
        #endregion

        #region Private Methods

        private bool AddPlaylist(string i_filename)
        {
            // Datei bereits in Liste ?
            bool allowAdd = true;
            foreach (PlaylistFile props in _playlistFiles)
            {
                if (props.Filename == i_filename)
                {
                    allowAdd = false;
                    MessageBox.Show("Die Playlist\n" + i_filename + "\nist bereits in der Liste !",
                                    "Datei bereits vorhanden", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    break;
                }
            }

            if (allowAdd)
            {
                PlaylistFile playlist = new PlaylistFile(menuPlaylistCF3.Checked);
                if (playlist.ParsePlaylist(i_filename))
                {
					// Erst Pfade ersetzen
					playlist.SetPaths(txtCentrafusePath.Text, txtMusicPath.Text);

                    playlist.CalcProperties(_audioFiles);

                    // Zur Liste hinzufügen
                    _playlistFiles.Add(playlist);

                    ShowPlaylistFile(playlist);
                }// if (playlist.ParseM3U(i_filename))
                else
                {
                    MessageBox.Show("Playliste\n" + i_filename + "\nkann nicht geöffnet werden",
                                    "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }// if (allowAdd)

            return allowAdd;
        } 

        private void GetAudioFiles()
        {
            // Verzeichnisinhalt neu abrufen
            if (txtMusicPath.Text.Length > 0)
            {
                Cursor = Cursors.WaitCursor;
                lblStatusStrip.Text = "Audiodateien werden aufgelistet...";
                Refresh();

                IEnumerable<string> filelist = null;
                try
                {
                    filelist = FileIterator.GetFiles(txtMusicPath.Text, "*.mp3");
					_logFile.WriteLine("GetAudioFiles: Filelist fetched");

                    _audioFiles.Clear();

                    if (filelist != null)
                    {
                        foreach (string filename in filelist)
                        {
                            _audioFiles.Add(new PlaylistAudioFile(filename));
                        }
                    }
					_logFile.WriteLine("GetAudioFiles: Audiofiles added");

                    // Playlistproperties neu berechnen
                    foreach (PlaylistFile playlist in _playlistFiles)
                    {
                        playlist.CalcProperties(_audioFiles);
                    }
					_logFile.WriteLine("GetAudioFiles: Playlistproperties calculated");                
                    
                    // Audiodateien anzeigen
                    ShowAudioFiles();
                    _logFile.WriteLine("GetAudioFiles: Audiofiles shown");               
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, "Fehler beim Abrufen der Dateiliste",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    lblStatusStrip.Text = _audioFiles.Count.ToString() + " Audiodateien geladen.";
                    Cursor = Cursors.Default;
                }

				_logFile.WriteLine("Audiofiles loaded(" + _audioFiles.Count + ")");
            }// if (txtMusicPath.Text.Length > 0)
        }

        private void ShowPlaylistFile(PlaylistFile i_playlist)
        {
            ListViewItem item;
            string[] subItems = new string[] { "", "", "" };

            item = new ListViewItem();
            item.ImageIndex = 1;
            item.Tag = i_playlist;
            item.Text = "";
            item.SubItems.Add(i_playlist.Filename);

            item.SubItems.AddRange(subItems);

            lstPlaylists.Items.Add(item);
            i_playlist.ListItem = item;

            grpPlaylistFiles.Text = "Playlisten - " + lstPlaylists.Items.Count;

            // Sortieren
            lstPlaylists.Sort();
        }

        private void ShowAudioFiles()
        {
			ListViewItem item = null;
            string[] subItems = new string[] {"","","",""};
            
            // Puffer für schnellere Suche
			_listViewItemBuffer = new List<ListViewItem>(_audioFiles.Count);

            foreach (PlaylistAudioFile props in _audioFiles)
            {
				item = new ListViewItem();
				item.ImageIndex = 0;
				item.Tag = props;
                // Nur Dateiname anzeigen
				item.Text = Path.GetFileName(props.FileName);

				item.SubItems.AddRange(subItems);

				props.ListItem = item;

				_listViewItemBuffer.Add(item);
            }// for (int i = 0; i < audioFileProps.Count; i++)

			lstAudioFiles.BeginUpdate();
			lstAudioFiles.Items.Clear();
			lstAudioFiles.Items.AddRange(_listViewItemBuffer.ToArray());
			// Sortieren
			lstAudioFiles.Sort();
			lstAudioFiles.EndUpdate();

            // Anzahl Audiofiles
            grpAudioFiles.Text = "Audiodateien - " + lstAudioFiles.Items.Count;
        }
        
        private void ShowPlaylistContents(PlaylistFile i_playlist)
        {
			ListViewItem item;
			List<ListViewItem> itemsList = new List<ListViewItem>(i_playlist.Entries.Count);
            string[] subItems = {"", "", "", "", "", ""};
            
            foreach (PlaylistEntry entry in i_playlist.Entries)
            {
                item = new ListViewItem();
                item.ImageIndex = 0;
                item.Text = "";
                item.SubItems.AddRange(subItems);
                item.Tag = entry;

                entry.SetListItem(item, lstPlaylistEntries.Groups[0], 
                                        lstPlaylistEntries.Groups[1], 
                                        lstPlaylistEntries.Groups[2]);

				// Item hinzufügen
				itemsList.Add(item);
            }// for (int i = 0; i < playlistProps[i_playlistIdx].playlistEntries.Count; i++)

			lstPlaylistEntries.BeginUpdate();
			lstPlaylistEntries.Items.Clear();
			lstPlaylistEntries.Items.AddRange(itemsList.ToArray());
			lstPlaylistEntries.EndUpdate();

            grpPlaylistEntries.Text = "Playlisteinträge - " + lstPlaylistEntries.Items.Count;
        }

        private void AddMultiplePlaylists(string[] i_filenames)
        {
            foreach (string filename in i_filenames)
            {
                AddPlaylist(filename);
            }

            // Neu sortieren
            lstPlaylists.Sort();
            lstAudioFiles.Sort();
        }

        private bool AddFileToPlaylist(PlaylistAudioFile i_file, PlaylistFile i_playlist)
        {
            bool allowAdd = true;
            bool duplicate = false;

            // Datei bereits in Liste ?
            foreach (PlaylistEntry entry in i_playlist.Entries)
            {
                if (entry.Audiofile == i_file)
                {
                    DialogResult res = MessageBox.Show("Die Datei\n[" + i_file.FileName +
                        "]\nist bereits in der Playliste\n[" + i_playlist.Filename +
                        "]\nvorhanden !\nTrotzdem hinzufügen ?",
                        "Datei bereits vorhanden",
                        MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (res == DialogResult.No)
                    {
                        allowAdd = false;
                    }
                    duplicate = true;

                    break;
                }
            }// foreach (PlaylistEntry entry in i_playlist.Entries)

            if (allowAdd)
            {
                i_playlist.AddAudioFile(i_file, duplicate);
            }

            return allowAdd;
        }

        private void PlaylistEntryEdit()
        {
            if (lstPlaylistEntries.SelectedItems.Count == 1)
            {
                _frmEntryDetails.PlaylistEntry = lstPlaylistEntries.SelectedItems[0].Tag as PlaylistEntry;

                if (_frmEntryDetails.PlaylistEntry.Audiofile != null)
                {
                    _frmEntryDetails.PlaylistEntry.Audiofile.LoadTags(true);
                }
                _frmEntryDetails.ShowDialog();
            }// if (lstPlaylistEntries.SelectedItems.Count == 1)
        }

        private void PlaylistEntryDelete()
        {
            if (lstPlaylistEntries.SelectedItems.Count > 0)
            {
                PlaylistEntry entry = null;
                for (int i = lstPlaylistEntries.SelectedItems.Count - 1; i > -1; i--)
                {
                    ListViewItem item = lstPlaylistEntries.SelectedItems[i];

                    // Entry holen
                    entry = item.Tag as PlaylistEntry;

                    if (entry.Audiofile != null)
                    {
                        // Playliste von Audiodatei entfernen
                        entry.Audiofile.RemovePlaylist(entry.Playlist);
                    }// if (entry.Audiofile != null)

                    // Playliste aktualisieren
                    lstPlaylistEntries.Items.Remove(item);
                    entry.Playlist.RemoveEntry(entry);
                }
            }// if (lstPlaylistEntries.SelectedItems.Count > 0)
        }

        private void PlaylistShowDetails()
        {
            if (lstPlaylists.SelectedItems.Count == 1)
            {
                _frmPlaylistDetails.Playlist = lstPlaylists.SelectedItems[0].Tag as PlaylistFile;
                _frmPlaylistDetails.ShowDialog();
            }// if (lstPlaylists.SelectedItems.Count == 1)
        }

        private void PlaylistDelete(PlaylistFile i_playlist)
        {
            // Geändert ?
            if (CheckForSaveNeed(i_playlist))
            {
                // Audiodatei Aktualisieren
                foreach (PlaylistEntry entry in i_playlist.Entries)
                {
                    if (entry.Audiofile != null)
                    {
                        entry.Audiofile.RemovePlaylist(i_playlist);
                    }// if (afIndex > -1)
                }// foreach (PlaylistEntry entry in playlistProps[index].playlistEntries)
                
                // Playliste Entfernen
                lstPlaylists.Items.Remove(i_playlist.ListItem);
                _playlistFiles.Remove(i_playlist);

                grpPlaylistFiles.Text = "Playlisten - " + _playlistFiles.Count.ToString();
            }
        }

        private bool CheckForSaveNeed(PlaylistFile i_playlist)
        {
            bool retVal = true;

            if (i_playlist.Changed)
            {
                DialogResult res = MessageBox.Show("Die Playliste\n[" + i_playlist.Filename
                    + "]\nwurde verändert !\nSollen die Änderungen gespeichert werden ?",
                    "Änderungen Speichern", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                // Speichern
                if (res == DialogResult.Yes)
                {
                    i_playlist.WritePlaylist();
                }
                // Nicht beenden
                else if (res == DialogResult.Cancel)
                {
                    retVal = false;
                }
            }// if (playlistProps[i_index].changed)

            return retVal;
        }

        private void AudiofileShowDetails(PlaylistAudioFile i_audiofile)
        {
            if (i_audiofile != null)
            {
                i_audiofile.LoadTags(true);

                _frmAudioDetails.Audiofile = i_audiofile;
                _frmAudioDetails.ShowDialog();
            }
        }

        private void SetViewAudiofiles(View i_view)
        {            
            // Check menu items
            cMenuAudioViewDetails.Checked = i_view == View.Details;
            cMenuAudioViewList.Checked = i_view == View.List;
            cMenuAudioViewSmallIcon.Checked = i_view == View.SmallIcon;
            cMenuAudioViewLargeIcon.Checked = i_view == View.LargeIcon;
            cMenuAudioViewTile.Checked = i_view == View.Tile;

            // Ansicht umschalten
            lstAudioFiles.View = i_view;
        }

        private void SetSortColumnAudiofiles(ColumnsAudiofile i_column)
        {
            // Sortierung ändern
            ListViewExtensions.ChangeSorting(lstAudioFiles, (int)i_column);

            // Contextmenu anpassen
            ListViewColumnSorter sorter = lstAudioFiles.ListViewItemSorter as ListViewColumnSorter;

            cMenuAudioOrderByCover.Image = i_column == ColumnsAudiofile.Cover ?
                (sorter.SortOrder == SortOrder.Ascending ?
                Properties.Resources.arrow_up : Properties.Resources.arrow_down) : null;
            
            cMenuAudioOrderByFilename.Image = i_column == ColumnsAudiofile.Filename ?
                (sorter.SortOrder == SortOrder.Ascending ?
                Properties.Resources.arrow_up : Properties.Resources.arrow_down) : null;

            cMenuAudioOrderByLyrics.Image = i_column == ColumnsAudiofile.Lyrics ?
                (sorter.SortOrder == SortOrder.Ascending ?
                Properties.Resources.arrow_up : Properties.Resources.arrow_down) : null;

            cMenuAudioOrderByPlaylists.Image = i_column == ColumnsAudiofile.NoOfPlaylists ?
                (sorter.SortOrder == SortOrder.Ascending ?
                Properties.Resources.arrow_up : Properties.Resources.arrow_down) : null;

            cMenuAudioOrderByTags.Image = i_column == ColumnsAudiofile.Tags ?
                (sorter.SortOrder == SortOrder.Ascending ?
                Properties.Resources.arrow_up : Properties.Resources.arrow_down) : null;
        }

        private void FilterAudiofiles()
        {
            string compareString = txtFilterAudiofiles.Text.ToLower();

            if (compareString != _currentFilter)
            {
                _currentFilter = compareString;

                // Cursor ändern
                Cursor = Cursors.WaitCursor;

				List<ListViewItem> itemsList = new List<ListViewItem>();

                // In Liste suchen
                foreach (ListViewItem item in _listViewItemBuffer)
                {
                    if (item.Text.ToLower().Contains(compareString))
                    {
						itemsList.Add(item);
                    }
                }

                lstAudioFiles.BeginUpdate();
                lstAudioFiles.Items.Clear();
                lstAudioFiles.Items.AddRange(itemsList.ToArray());
				lstAudioFiles.EndUpdate();
				
                grpAudioFiles.Text = "Audiodateien - " + lstAudioFiles.Items.Count;

                // Cursor auf Default
                Cursor = Cursors.Default;
            }
        }

        private void SwitchMPLPlaylistVersion()
        {
            Properties.Settings.Default.UseCF3StyleMPL = menuPlaylistCF3.Checked = !menuPlaylistCF3.Checked;
            menuPlaylistCF2.Checked = !menuPlaylistCF3.Checked;

            foreach (PlaylistFile pl in _playlistFiles)
            {
                pl.UseCF3StyleMPL = menuPlaylistCF3.Checked;
            }
        }

		private void ReplaceAllPlaylistPaths()
		{
			foreach (PlaylistFile playlist in _playlistFiles)
			{
				playlist.SetPaths(txtCentrafusePath.Text, txtMusicPath.Text);
			}
		}

		private void SortSelectedPlaylists()
		{
			foreach (ListViewItem item in lstPlaylists.SelectedItems)
			{
				(item.Tag as PlaylistFile).Sort();
			}

			if (lstPlaylists.SelectedItems.Count == 1)
			{
				ShowPlaylistContents(lstPlaylists.SelectedItems[0].Tag as PlaylistFile);
			}
		}

		#endregion

	}
}
